package com.example.chamberlainserver.security;

import com.example.chamberlainserver.Entry.User;
import com.example.chamberlainserver.Entry.Role;
import com.example.chamberlainserver.Service.UserService;
import com.example.chamberlainserver.Service.UserRoleService;

import java.util.List;
import com.example.chamberlainserver.event.AuthenticationEvent;
import com.example.chamberlainserver.event.AuthenticationResultEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class SecurityEventListener {

    private final AuthenticationManager authenticationManager;
    private final JwtUserDetailsService userDetailsService;
    private final JwtTokenUtil jwtTokenUtil;
    private final ApplicationEventPublisher eventPublisher;
    private final UserService userService;
    private final UserRoleService userRoleService;
    
    @Autowired
    public SecurityEventListener(AuthenticationManager authenticationManager,
                               JwtUserDetailsService userDetailsService,
                               JwtTokenUtil jwtTokenUtil,
                               ApplicationEventPublisher eventPublisher,
                               UserService userService,
                               UserRoleService userRoleService) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtTokenUtil = jwtTokenUtil;
        this.eventPublisher = eventPublisher;
        this.userService = userService;
        this.userRoleService = userRoleService;
    }
    
    @EventListener
    public void handleAuthenticationEvent(AuthenticationEvent event) {
        try {
            // 认证用户
            authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(event.getUsername(), event.getPassword()));
            
            // 加载用户详情
            UserDetails userDetails = userDetailsService.loadUserByUsername(event.getUsername());
            
            // 获取用户ID和角色
            User user = userService.getUserByStuNo(event.getUsername());
            if (user == null) {
                throw new UsernameNotFoundException("未找到用户: " + event.getUsername());
            }
            int userId = user.getId(); // 直接使用int类型
            String role = getPrimaryUserRole(userId);
            
            // 生成包含用户ID和角色的令牌
            String token = jwtTokenUtil.generateToken(userDetails, userId, role);
            
            // 发布成功事件
            eventPublisher.publishEvent(new AuthenticationResultEvent(
                this, event.getUsername(), token, true, null));
                
        } catch (DisabledException e) {
            // 发布失败事件
            eventPublisher.publishEvent(new AuthenticationResultEvent(
                this, event.getUsername(), null, false, "用户已被禁用"));
        } catch (BadCredentialsException e) {
            // 发布失败事件
            eventPublisher.publishEvent(new AuthenticationResultEvent(
                this, event.getUsername(), null, false, "无效的凭证"));
        } catch (Exception e) {
            // 发布失败事件
            eventPublisher.publishEvent(new AuthenticationResultEvent(
                this, event.getUsername(), null, false, e.getMessage()));
        }
    }
    
    /**
     * 获取用户的主要角色
     */
    private String getPrimaryUserRole(Integer userId) {
        List<Role> roles = userRoleService.getRolesByUserId(userId);
        if (roles != null && !roles.isEmpty()) {
            // 返回第一个角色的角色代码
            return roles.get(0).getRoleCode();
        }
        // 如果没有角色，返回默认角色
        return "STUDENT";
    }
}